import java.util.HashSet;
import java.util.Random;
import java.util.Set;

/**
 * 加减法口算练习系统-v0.3
 * 故事三：避免重复算式，确保有加法和减法
 * 新增功能：
 * 1. 生成没有重复算式的习题
 * 2. 确保习题中既有加法又有减法
 */
public class CalculationSystemV03 {
    private Random random;

    public CalculationSystemV03() {
        this.random = new Random();
    }

    /**
     * 生成指定范围内的随机数
     * @param min 最小值（包含）
     * @param max 最大值（不包含）
     * @return 随机整数
     */
    private int generateRandomNumber(int min, int max) {
        return random.nextInt(max - min) + min;
    }

    /**
     * 算式数据结构：使用内部类表示算式
     */
    public static class Equation {
        int num1;
        int num2;
        boolean isAddition;
        int answer;
        String expression;
        String key; // 用于去重的唯一标识

        public Equation(int num1, int num2, boolean isAddition) {
            this.num1 = num1;
            this.num2 = num2;
            this.isAddition = isAddition;

            if (isAddition) {
                this.answer = num1 + num2;
                this.expression = num1 + " + " + num2 + " = " + answer;
                // 使用有序的key来避免重复（如 3+5 和 5+3 视为相同）
                this.key = Math.min(num1, num2) + "+" + Math.max(num1, num2);
            } else {
                this.answer = num1 - num2;
                this.expression = num1 + " - " + num2 + " = " + answer;
                // 减法算式的key就是唯一的
                this.key = num1 + "-" + num2;
            }
        }

        @Override
        public String toString() {
            return expression;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null || getClass() != obj.getClass()) return false;
            Equation equation = (Equation) obj;
            return key.equals(equation.key);
        }

        @Override
        public int hashCode() {
            return key.hashCode();
        }
    }

    /**
     * 生成一道加法算式（和不超过100）
     * @return 算式对象
     */
    private Equation generateAdditionEquation() {
        int num1 = generateRandomNumber(0, 101); // 0-100
        int maxNum2 = 100 - num1;
        int num2 = generateRandomNumber(0, maxNum2 + 1);

        return new Equation(num1, num2, true);
    }

    /**
     * 生成一道减法算式（差不小于0）
     * @return 算式对象
     */
    private Equation generateSubtractionEquation() {
        int num1 = generateRandomNumber(0, 101); // 0-100
        int num2 = generateRandomNumber(0, num1 + 1);

        return new Equation(num1, num2, false);
    }

    /**
     * 生成50道不重复的习题，确保有加法和减法
     */
    public void generateExercises() {
        System.out.println("加减法口算练习系统-v0.3");
        System.out.println("========================");
        System.out.println("生成50道不重复的100以内加减法算式（带答案）：\n");

        Set<Equation> equationSet = new HashSet<>();
        Set<String> usedKeys = new HashSet<>(); // 用于快速检查重复

        // 确保至少有一定数量的加法和减法
        int minAddition = 10; // 至少10道加法
        int minSubtraction = 10; // 至少10道减法

        // 先生成最少数量的加法和减法
        while (equationSet.size() < minAddition) {
            Equation eq = generateAdditionEquation();
            if (!usedKeys.contains(eq.key)) {
                equationSet.add(eq);
                usedKeys.add(eq.key);
            }
        }

        while (equationSet.size() < minAddition + minSubtraction) {
            Equation eq = generateSubtractionEquation();
            if (!usedKeys.contains(eq.key)) {
                equationSet.add(eq);
                usedKeys.add(eq.key);
            }
        }

        // 继续生成剩余的算式，直到达到50道
        int maxAttempts = 10000; // 防止无限循环
        int attempts = 0;

        while (equationSet.size() < 50 && attempts < maxAttempts) {
            attempts++;
            boolean isAddition = random.nextBoolean();
            Equation eq = isAddition ? generateAdditionEquation() : generateSubtractionEquation();

            if (!usedKeys.contains(eq.key)) {
                equationSet.add(eq);
                usedKeys.add(eq.key);
            }
        }

        // 转换为数组以便输出
        Equation[] equations = equationSet.toArray(new Equation[0]);

        // 统计加法和减法的数量
        int additionCount = 0;
        int subtractionCount = 0;
        for (Equation eq : equations) {
            if (eq.isAddition) {
                additionCount++;
            } else {
                subtractionCount++;
            }
        }

        // 每行显示5个算式，整齐排列
        int equationsPerLine = 5;
        for (int i = 0; i < equations.length; i++) {
            System.out.printf("%2d. %-20s", i + 1, equations[i].toString());

            if ((i + 1) % equationsPerLine == 0) {
                System.out.println();
            }
        }

        if (equations.length % equationsPerLine != 0) {
            System.out.println();
        }

        System.out.println("\n统计信息：");
        System.out.println("总题数：" + equations.length);
        System.out.println("加法题数：" + additionCount);
        System.out.println("减法题数：" + subtractionCount);
    }

    public static void main(String[] args) {
        CalculationSystemV03 system = new CalculationSystemV03();
        system.generateExercises();
    }
}
